#include <GameLogic/Include/GameLogic.h>

#include <Render/Include/RendererDX9.h>
#include <Render/Include/RendererDX11.h>
#include <Render/Include/RendererOGL.h>

#include <Model/Include/Element.h>

#include <sstream>

GameLogic::GameLogic(Render::IWinWindow* window, const GameRenderingPlatform &platform, Render::IWinWindow* auxi_window)
{
    this->window = window;
    switch (platform)
    {
    case GameRenderingPlatform::RENDER_WITH_DX9:
        this->renderer = new Render::RendererDX9(window);
        break;
    case GameRenderingPlatform::RENDER_WITH_DX11:
        this->renderer = new Render::RendererOGL(window, auxi_window);//new Render::RendererDX11(window);
        break;
    default:
        throw -1;
    }
    
    this->view_in_3D = false;
    this->renderer->render2D();

    this->scene = NULL;
    this->game_finished = false;

    this->main_task = new Task(main_task_function, this, T_TaskPriority::TASK_PRIORITY_ABOVE_NORMAL, 40);
    this->time_meter = new TimeMeter();

    this->player_points = 0;
}


GameLogic::~GameLogic(void)
{
    delete this->renderer;
    delete this->time_meter;
}

void GameLogic::load(const int &scene_size, const int &snake_velocity)
{
    this->snake = new Model::Snake(scene_size/2, scene_size/2);
    this->snake->setVelocity(snake_velocity);
    this->scene = new Model::Scene(scene_size, scene_size, snake); 
}

void GameLogic::unload()
{
    delete this->snake;
    this->snake = NULL;
    delete this->scene;
    this->scene = NULL;
}

void GameLogic::changeView()
{
    this->view_in_3D = !view_in_3D;
    if(this->view_in_3D)
    {
        this->renderer->render3D();
    }
    else
    {
        this->renderer->render2D();
    }
}

void GameLogic::run()
{
    this->time_meter->start();
    //this->main_task->start();    
}


void GameLogic::main_task_function(void* user_data)
{
    GameLogic* game = (GameLogic*)user_data;
    int time_elapsed = (int)game->time_meter->end();
    game->time_meter->start();
    if (!game->game_finished)
    {
        game->scene->progress(time_elapsed);
        if (game->scene->checkSnakeVsFreeElement())
        {
            game->player_points++;
        }
        game->game_finished = game->scene->checkSnakeCollition();
        game->addGameText();
        game->renderer->renderScene(game->scene);        
    }
    else
    {
        char auxi[200];
        sprintf(auxi, "GAME OVER! Your Score was: %d ", game->player_points);
        std::string msg = auxi;
        game->renderer->addText(msg, game->window->getWidth()/5, game->window->getHeight()/2);
        game->renderer->renderBlack();
        game->main_task->stop(); 
    }    
}

void GameLogic::addGameText()
{
    char auxi[200];
    sprintf(auxi, "Score: %d", this->player_points);
    std::string text = auxi;
    
    this->renderer->addText(text, 10 , 10);
}

void GameLogic::input(const GameInputType &input_type)
{
    switch (input_type)
    {
    case GameInputType::LEFT_ARROW_PRESSED:
        this->snake->turnLeft();
    	break;
    case GameInputType::RIGHT_ARROW_PRESSED:
        this->snake->turnRight();
        break;
    }    
}

bool GameLogic::hasTheGameFinished() const
{
    return this->game_finished;
}
